<?php
// +----------------------------------------------------------------------
// | B5Yii2CMF V3.0 [快捷通用基础管理开发平台]
// +----------------------------------------------------------------------
// | Author: 冰舞 <357145480@qq.com>
// +----------------------------------------------------------------------
declare (strict_types = 1);

namespace common\helpers;

/**
 * AES/DES加密
 *  $crypt = new CryptHelper('1234567890654321','1234567890123456');
    $code = $crypt->encrypt('123');

 */
class CryptHelper
{
    /**
     * 加密模式
     * @var string
     */
    public string $cipher = 'AES-128-CBC';

    /**
     * 密钥
     * @var string
     */
    public string $secret_key = '';

    /**
     * 偏移量 CBC需要iv
     * @var string
     */
    public string $iv = '';

    /**
     * @var bool 加密解密前是否使用base64编码
     * 前端crypto-js 都是进行了base64加密
     */
    public bool $base64 = true;

    /**
     * 补位方式
     * 0 默认
     * OPENSSL_RAW_DATA = 1  对应PKCS7
     * OPENSSL_ZERO_PADDING = 2 使用0填充
     * OPENSSL_NO_PADDING = 3 不填充，需要手动填充
     * @var int
     */
    public int $pad = 1;

    // 可以使用openssl_get_cipher_methods()查看所有加密模式
    // [16,32 ] 第一位16是iv的长度   第二位32是密钥的长度
    // 长度是对应长度的字符串或者转换的16进制
    private array $allowedCiphers = [
        'AES-128-CBC' => [16, 16],
        'AES-192-CBC' => [16, 24],
        'AES-256-CBC' => [16, 32],
        'AES-128-ECB' => [0, 16],
        'AES-256-ECB' => [0, 32],
        'DES-ECB' => [0,8],
        'DES-CBC' => [16,8]
    ];


    public function __construct($secret_key = '',$iv = '',$cipher = '')
    {
        if($cipher) $this->cipher = $cipher;
        if($secret_key) $this->secret_key = $secret_key;
        if($iv) $this->iv = $iv;
    }

    /**
     * 加密
     * @param $data
     * @return string
     */
    public function encrypt($data): string
    {
        //如果是在php间使用，这里可以使用 serialize() / unserialize()
        // 这里使用json_encode 主要是为了和前端js交互
        if(is_array($data)) $data = json_encode($data);
        $str = '';
        if ($data){
            $size = $this->allowedCiphers[$this->cipher]??[];
            $ivSize = $size[0]??0;
            $str = openssl_encrypt($data,$this->cipher,$this->secret_key,$this->pad,$ivSize>0?$this->iv:"");
            if($str && $this->base64){
                $str =  base64_encode($str);
            }
        }
        return $str?:'';
    }

    /**
     * 解密
     * @param string $data
     * @return string
     */
    public function decrypt($data): string
    {
        if($this->base64) $data = base64_decode($data);
        $result = '';
        if($data){
            $size = $this->allowedCiphers[$this->cipher]??[];
            $ivSize = $size[0]??0;
            $result = openssl_decrypt($data,$this->cipher,$this->secret_key,$this->pad,$ivSize>0?$this->iv:"");
        }
        return $result?:'';
    }


    /**
     * @description  RSA公钥加密 私钥解密
     * @param string $data 待加解密数据
     * @param bool $isEn true:加密 false:解密
     * @return string 返回加密内容/解密内容
     */
    public static function RSACrypt($data, $isEn = true): string
    {
        //RSA 公钥
        $rsa_public = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMf2TfuRKZHYkaTWNlAHezZrqDQ3oVcXKBG4A6g+VvL1za+I2XoJ4htKiFtFUa1BRdbD948L+6sm/G3Te7dGfClzoadYlLLt+BZ1R5EoxvfGwxzvD99EJgiYm6Y2jLnkIF3GOM1ISIZjTY0xumGw5218DADMEp/xnPNhuVw8H3iwIDAQAB';

        //RSA 私钥
        $rsa_private = 'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIx/ZN+5EpkdiRpNY2UAd7NmuoNDehVxcoEbgDqD5W8vXNr4jZegniG0qIW0VRrUFF1sP3jwv7qyb8bdN7t0Z8KXOhp1iUsu34FnVHkSjG98bDHO8P30QmCJibpjaMueQgXcY4zUhIhmNNjTG6YbDnbXwMAMwSn/Gc82G5XDwfeLAgMBAAECgYA1VvREH65Y5Sa1DqZqpRfMy3aJ+SczVuPC8l7nWEXVxWR6WZzf8QG4CC9mu4UH73Zf1YXvc29HARGArWHIUDRH0xlchfTnDPvEbzeIueWBBDUCvE6FO4TeZoO9PrgFluZ1Aw/eZhkeVlL6GFhol48JZrLXwqsRFvNDCTo9Px0wEQJBAMbqPxb9swATOLIRbYhgvWZXRYj1x4FewbmWAagSFqBDQbyVpsf/aYoDncajagyvJfqYSi3ARuMz5cNd/0wUELMCQQC00WDgM9w8OhqvhV5PYyy5OTPUddytVFjibfpJ1piF++1gsBORUyR7z+8ND629R0f/Xcsz3mQE9dmEDdjhEznJAkBO4KzL7SaCLR0aX5bTsajpYEoOmYfXYT/o2/ckMqgOPR1gLufH/xxWwkBaeIqhJQMmcCVaJxj1F6tQ4YFPJdXJAkBJLAXxFOuF79mGuAjvRWn+1rgzvTJ9bgm+L9U+djoo1kc8fmScxbGY7Q+HEJY1Z5gqLjGiHtgI7diFSPlANACJAkAy1r+5qK2GQMSGn5az+QZqsNM7mqRxq323Zsrmoi4Tzzh5kKR9sCwsCphrgjgEaZt3yGiuUAiDUDCB6u3vHUSb';

        //RSA 公钥加密
        if ($isEn) {
            $public_key = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($rsa_public, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
            $key = openssl_pkey_get_public($public_key);
            if (!$key) {
//                echo '公钥不可用';
                return '';
            }
            $return_en = openssl_public_encrypt($data, $crypted, $key);
            if (!$return_en) {
//                echo '公钥加密失败';
                return '';
            }
            return base64_encode($crypted);
        }else{
            //RSA 私钥解密
            $private_key = "-----BEGIN PRIVATE KEY-----\n" . wordwrap($rsa_private, 64, "\n", true) . "\n-----END PRIVATE KEY-----";
            $key = openssl_pkey_get_private($private_key);
            if (!$key) {
//                echo '私钥不可用';
                return '';
            }
            $return_de = openssl_private_decrypt(base64_decode($data), $decrypted, $key);
            if (!$return_de) {
//                echo '私钥解密失败';
                return '';
            }
            return $decrypted;
        }
    }
}